package com.hk.web.controller.api;

import com.hk.commons.JsonResult;
import com.hk.commons.ProcessAPI;
import com.hk.commons.enums.Whether;
import com.hk.commons.exceptions.ValidateException;
import com.hk.web.controller.Routes;
import com.hk.web.domain.entity.RoleAssignMenu;
import com.hk.web.domain.entity.UserAssignRole;
import com.hk.web.domain.entity.UserRole;
import com.hk.web.domain.lifeCycle.repository.UserAssignRoleRepository;
import com.hk.web.domain.lifeCycle.repository.UserRoleRepository;
import com.hk.web.domain.lifeCycle.repository.UserRoleSpecification;
import com.hk.web.dto.UserAssignRoleDTO;
import com.hk.web.dto.UserRoleDTO;
import com.hk.web.dto.UserRoleQueryDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.MediaType;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * Created by Antinomy on 17/7/25.
 */
@RestController
@Api(value = "用户角色模块", description = "用户角色模块")
public class UserRoleAPIController {

    @Autowired
    private UserRoleRepository userRoleRepo;

    @Autowired
    private UserAssignRoleRepository userAssignRoleRepo;

    @ApiOperation(value = "创建角色", notes = "输入角色基本信息", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParam(name = "dto", value = "角色基本信息", required = true, dataType = "UserRoleDTO")
    @RequestMapping(value = Routes.USER_ROLE_CREATE, method = RequestMethod.POST)
    @ResponseBody
    public JsonResult create(HttpServletRequest request, @RequestBody UserRoleDTO dto) {

        ProcessAPI api = (jsonResult, validate) -> {
            validate.check("name", dto.getName());

            UserRole userRole = new UserRole();
            userRole.setName(dto.getName());
            userRole.setRoleType(dto.getRoleType());
            userRole.setDescription(dto.getDescription());
            userRole.setCreator(dto.getCreator());
            userRole.setUuid(UUID.randomUUID().toString());

            userRole = userRoleRepo.saveAndFlush(userRole);

            HashMap result = new HashMap();
            result.put("name", userRole.getName());
            result.put("uuid", userRole.getUuid());
            result.put("id", userRole.getId());

            jsonResult.result = result;
            jsonResult.size = 1L;
        };

        return api.process(request);

    }

    @ApiOperation(value = "查询角色", notes = "查询角色基本信息", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParam(name = "roleId", value = "角色基本信息", required = true, dataType = "Long", paramType = "path")
    @RequestMapping(value = Routes.USER_ROLE, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult show(HttpServletRequest request, @PathVariable Long roleId) {

        ProcessAPI api = (jsonResult, validate) -> {
            validate.check("roleId", roleId);

            UserRole userRole = userRoleRepo.findOne(roleId);

            if(userRole == null)
                throw new ValidateException("查无此角色");


            jsonResult.result = userRole;
            jsonResult.size = 1L;
        };

        return api.process(request);

    }

    @ApiOperation(value = "修改角色", notes = "修改角色角色基本信息", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "dto", value = "角色基本信息", required = true, dataType = "UserRoleDTO"),
            @ApiImplicitParam(name = "roleId", value = "角色基本信息", required = true, dataType = "Long", paramType = "path")
    })
    @RequestMapping(value = Routes.USER_ROLE, method = RequestMethod.POST)
    @ResponseBody
    public JsonResult update(HttpServletRequest request, @RequestBody UserRoleDTO dto, @PathVariable Long roleId) {

        ProcessAPI api = (jsonResult, validate) -> {
            validate.check("roleId", roleId);

            UserRole userRole = userRoleRepo.findOne(roleId);

            if(userRole == null)
                throw new ValidateException("查无此角色");

            userRole.setName(dto.getName());
            userRole.setRoleType(dto.getRoleType());
            userRole.setDescription(dto.getDescription());
            userRole.setCreator(dto.getCreator());

            userRole = userRoleRepo.saveAndFlush(userRole);

            jsonResult.result = userRole;
            jsonResult.size = 1L;
        };

        return api.process(request);

    }

    @ApiOperation(value = "修改角色", notes = "修改角色角色基本信息", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "roleId", value = "角色基本信息", required = true, dataType = "Long", paramType = "path")
    })
    @RequestMapping(value = Routes.USER_ROLE_DELETE, method = RequestMethod.POST)
    @ResponseBody
    public JsonResult delete(HttpServletRequest request, @PathVariable Long roleId) {

        ProcessAPI api = (jsonResult, validate) -> {
            validate.check("roleId", roleId);

            UserRole userRole = userRoleRepo.findOne(roleId);

            if(userRole == null)
                throw new ValidateException("查无此角色");

            List<UserAssignRole> assignRoles = userAssignRoleRepo.findByRoleId(roleId);

            if(assignRoles != null && assignRoles.size() > 0)
                throw new ValidateException("该角色已分配人员，不能删除！");

            userRole.setDeleted(Whether.YES);
            userRole = userRoleRepo.saveAndFlush(userRole);

            jsonResult.result = userRole.getName()+"角色已删除成功！";
            jsonResult.size = 1L;
        };

        return api.process(request);

    }

    @ApiOperation(value = "角色列表", notes = "角色列表", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @RequestMapping(value = Routes.USER_ROLE_LIST, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult list(HttpServletRequest request, UserRoleQueryDTO dto) {

        ProcessAPI api = (jsonResult, validate) -> {
            Specification<UserRole> userRoleSpecification = UserRoleSpecification.buildFromDTO(dto);
            Page<UserRole> userRoles = userRoleRepo.findAll(userRoleSpecification, dto.getPage());

            jsonResult.result = userRoles.getContent();
            jsonResult.size = userRoles.getTotalElements();
        };

        return api.process(request);

    }

    @ApiOperation(value = "用户分配角色", notes = "用户分配角色", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "dto", value = "用户分配角色参数", required = true, dataType = "UserAssignRoleDTO")
    })
    @RequestMapping(value = Routes.USER_ASSIGN_ROLE, method = RequestMethod.POST)
    @ResponseBody
    @Transactional
    public JsonResult userAssignRoles(HttpServletRequest request, @RequestBody UserAssignRoleDTO dto) {

        ProcessAPI api = (jsonResult, validate) -> {
            validate.check("userId", dto.getUserId());
            List<Long> roleIds = dto.getRoleIds();
            validate.check("roleIds", roleIds);

            if (roleIds.size() <= 0) {
                userAssignRoleRepo.deleteByUserId(dto.getUserId());
                return;
            }

            ArrayList<String> result = new ArrayList<>();

            roleIds.parallelStream().forEach(roleId -> {
                UserRole userRole = userRoleRepo.findOne(roleId);

                if (userRole == null)
                    throw new ValidateException("请选择有效角色Id:" + roleId);

                result.add(userRole.getName());
            });

            userAssignRoleRepo.deleteByUserId(dto.getUserId());

            roleIds.parallelStream().forEach(roleId -> {
                UserAssignRole userAssignRole = new UserAssignRole();
                userAssignRole.setUserId(dto.getUserId());
                userAssignRole.setRoleId(roleId);
                userAssignRoleRepo.saveAndFlush(userAssignRole);
            });

            jsonResult.result = result;
            jsonResult.size = (long) roleIds.size();
        };

        return api.process(request);

    }

    @ApiOperation(value = "查询用户分配角色", notes = "查询用户分配角色", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ApiImplicitParam(name = "userId", value = "用户Id", required = true, dataType = "Long", paramType = "query")
    @RequestMapping(value = Routes.USER_ASSIGN_ROLE, method = RequestMethod.GET)
    @ResponseBody
    public JsonResult getUserAssignedRoles(HttpServletRequest request, @RequestParam Long userId) {

        ProcessAPI api = (jsonResult, validate) -> {
            validate.check("userId", userId);

            List<UserAssignRole> assignRoles = userAssignRoleRepo.findByUserId(userId);

            List<Long> roleIds = assignRoles.parallelStream()
                    .map(UserAssignRole::getRoleId)
                    .collect(Collectors.toList());

            List<UserRole> roles = userRoleRepo.findAll(roleIds);

            if(assignRoles == null)
                throw new ValidateException("查无已分配角色");


            jsonResult.result = roles;
            jsonResult.size = (long)roles.size();
        };

        return api.process(request);

    }
}
